/**
 * @author: zhangguojin
 * @date: 2021/3/22 10:47
 * @description: 前端工具类方法
 */

/**
 * @author: panhuajian
 * @description: 防抖
 * @param: callback { function } 需要防抖的函数
 * @param: delay { number } 延时
 * @param: [immediate] { boolean } 是否立即执行
 * @return: [ function ] 回调函数
 **/
export const debounce = (callback, delay = 500, immediate = false) => {
  let timer = null;
  let tempImmediate = immediate;
  return function(...rest) {
    let _this = this;
    // 清除上一次延时器
    clearTimeout(timer);
    if (tempImmediate) {
      callback.apply(_this, rest);
      tempImmediate = false;
    } else {
      timer = setTimeout(() => {
        callback.apply(_this, rest);
      }, delay);
    }
  };
};

/**
 * @author: panhuajian
 * @description: 节流
 * @param: callback { function } 需要防抖的函数
 * @param: [delay] { number } 延时
 * @param: [immediate] { boolean } 是否立即执行
 * @return: { function } 回调函数
 */
export const throttle = (callback, delay = 500, immediate = false) => {
  let timer = null;
  let lastTime;
  let tempImmediate = immediate;
  return function(...rest) {
    let _this = this;
    let now = Date.now();
    // 清除上一次延时器
    clearTimeout(timer);
    if (tempImmediate) {
      callback.apply(_this, rest);
      tempImmediate = false;
      lastTime = Date.now();
    } else if (lastTime && now - lastTime >= delay) {
      callback.apply(_this, rest);
      lastTime = Date.now();
    } else {
      lastTime = Date.now();
      const remaining = delay - (now - lastTime);
      timer = setTimeout(() => {
        callback.apply(_this, rest);
      }, remaining);
    }
  };
};

/**
 * @author: panhuajian
 * @description: 解析小数返回百分数
 * @param: decimal { number } 原小数
 * @param: num { number } 保留小数位
 * @return: { string } 返回百分数
 */
export const parseDecimal = (decimal, num) => {
  let percent = "";

  if (decimal === null) {
    return percent;
  }

  if (!num) {
    num = 2;
  }

  percent = (decimal * 100).toFixed(num) + "%";

  return percent;
};

/**
 * @author: panhuajian
 * @description: 解析数据字典
 * @param: dataSource { array } 字典数据
 * @param: value { number | string } 需要转换的值
 * @param: valueKey { string } 值对应的字段
 * @param: labelKey { string } 显示数据对应的字段
 * @return:  { string } 字典的name
 */
export const parseDictionary = (
  dataSource,
  value,
  valueKey = `value`,
  labelKey = `label`
) => {
  if (value === "" || value === null) {
    return "";
  }
  if (!dataSource) {
    return "";
  }

  let obj = dataSource.find((item) => {
    return item[valueKey] == value;
  });

  if (obj) {
    return obj[labelKey];
  } else {
    return "";
  }
};

/**
 * @author: panhuajian
 * @description: 深拷贝
 * @param: target { object | array | null}  深拷贝的原对象
 * @retrun: { object | array | null} 深拷贝之后的对象
 */
export const deepClone = (target) => {
  // 定义一个变量
  let result;
  // 如果当前需要深拷贝的是一个对象的话
  if (typeof target === `object`) {
    // 如果是一个数组的话
    if (Array.isArray(target)) {
      result = []; // 将result赋值为一个数组，并且执行遍历
      for (let i in target) {
        // 递归克隆数组中的每一项
        result.push(deepClone(target[i]));
      }
      // 判断如果当前的值是null的话；直接赋值为null
    } else if (target === null) {
      result = null;
      // 判断如果当前的值是一个RegExp对象的话，直接赋值
    } else if (target.constructor === RegExp) {
      result = target;
    } else {
      // 否则是普通对象，直接for in循环，递归赋值对象的所有值
      result = {};
      for (let i in target) {
        result[i] = deepClone(target[i]);
      }
    }
    // 如果不是对象的话，就是基本数据类型，那么直接赋值
  } else {
    result = target;
  }
  // 返回最终结果
  return result;
};

/**
 * @author: panhuajian
 * @description: 构造树型结构数据
 * @param: data { array } 数据源
 * @param: id { string } 数据唯一标识字段,默认 'id'
 * @param: parentId { string } 父节点字段,默认 'parentId'
 * @return: { array } 处理之后的树形结构数据
 */
export const handleTree = (data, id = `id`, parentId = `parentId`) => {
  const newData = deepClone(data);
  const result = [];
  const listMap = {};
  newData.forEach((item) => {
    listMap[item[id]] = item;
  });
  newData.forEach((item) => {
    const parent = listMap[item[parentId]];
    if (parent) {
      if (parent.children) {
        parent.children.push(item);
      } else {
        parent.children = [];
        parent.children.push(item);
      }
      parent.children.sort((a, b) => {
        return a.orderNo - b.orderNo;
      });
    } else {
      result.push(item);
      result.sort((a, b) => {
        return a.orderNo - b.orderNo;
      });
    }
  });
  return result;
};

/**
 * @author: panhuajian
 * @description: 数字千分位分割，10000 => "10,000"
 * @param: number { number } 需要转换的数字
 * @return: { string } 转换千分位之后的字符串
 */
export const toThousandFilter = (number) => {
  if (typeof number === `number`) {
    let tempNum = [];
    const num = number
      .toString()
      .split(``)
      .reverse();
    for (let i = 0; i < num.length; i++) {
      if ((i + 1) % 3 === 0 && i + 1 < num.length) {
        tempNum.push(`${num[i]}`);
        tempNum.push(`,`);
      } else {
        tempNum.push(`${num[i]}`);
      }
    }
    return tempNum.reverse().join(``);
  } else if (number !== undefined) {
    console.error(`错误：数字分割千分位是需要传入number类型`);
  }
  return number;
};

/**
 * @author: panhuajian
 * @description: 文件下载
 * @param: url { string } 下载地址 必须
 * @param: name { string } 文件名称
 * @return: { void }
 */
export const downloadFile = (url, name) => {
  if (!url) return;
  let a = document.createElement(`a`); //创建a标签
  a.style.display = `none`; //使其隐藏
  a.href = url; //赋予文件下载地址
  a.setAttribute(`download`, name); //设置下载属性 以及文件名
  document.body.appendChild(a); //a标签插至页面中
  a.click(); //强制触发a标签事件
  document.body.removeChild(a);
};

/**
 * @author: panhuajian
 * @description: 表单校验
 * @param: rule { object | array } 校验规则
 * @param: value { any } 表单项值
 * @param: callback { function } 回调函数
 * @return: { void }
 */
export const validate = (rule, value, callback, ...validateList) => {
  const validateResult = validateList.find((item) => {
    const type = Object.prototype.toString.call(item);
    if (type === `[object Function]`) {
      const resultData = item(value);
      if (!resultData.verify) {
        callback(resultData.message);
        return true;
      }
    } else if (type === `[object Object]`) {
      const resultData = item.validate(value, item.message);
      if (!resultData.verify) {
        callback(resultData.message);
        return true;
      }
    } else {
      console.error(`validator: 参数应为Function或者Object形式`);
      return true;
    }
  });
  if (!validateResult) {
    callback();
  }
};

/**
 * 合并单元格
 * @author: zhangguojin
 * @param: {data} Array 排过序的表格数据
 * @param: {mergeField} String 需要合并的字段
 * @param: {rowIndex} Number 表格的行索引
 * @param: {relatedFields} Array 相关联的字段集合
 * @param: {mergeEmpty} Boolean 是否合并空单元格 默认false不合并
 */
export const mergeTableCell = (
  data,
  mergeField,
  rowIndex,
  relatedFields = [],
  mergeEmpty = false
) => {
  let rfLen = relatedFields.length;

  let fieldName = data[rowIndex][mergeField]; //当前行的字段
  if (rfLen > 0) {
    for (let i = 0; i < rfLen; i++) {
      fieldName += data[rowIndex][relatedFields[i]];
    }
  }
  if (!fieldName && !mergeEmpty) {
    return false;
  }
  if (rowIndex > 0) {
    let preFieldName = data[rowIndex - 1][mergeField]; //上一行的字段
    if (rfLen > 0) {
      for (let i = 0; i < rfLen; i++) {
        preFieldName += data[rowIndex - 1][relatedFields[i]];
      }
    }
    if (fieldName !== preFieldName) {
      let i = rowIndex;
      let num = 0;
      while (i < data.length) {
        let fieldName2 = data[i][mergeField];
        if (rfLen > 0) {
          for (let j = 0; j < rfLen; j++) {
            fieldName2 += data[i][relatedFields[j]];
          }
        }
        if (fieldName2 === fieldName) {
          i++;
          num++;
        } else {
          i = data.length;
        }
      }
      return {
        rowspan: num,
        colspan: 1,
      };
    } else {
      return {
        rowspan: 0,
        colspan: 1,
      };
    }
  } else {
    let i = rowIndex;
    let num = 0;
    while (i < data.length) {
      let fieldName2 = data[i][mergeField];
      if (rfLen > 0) {
        for (let j = 0; j < rfLen; j++) {
          fieldName2 += data[i][relatedFields[j]];
        }
      }
      if (fieldName2 === fieldName) {
        i++;
        num++;
      } else {
        i = data.length;
      }
    }
    return {
      rowspan: num,
      colspan: 1,
    };
  }
};

/**
 * 格式化数值 保留小数后几位数
 * @author: zhangguojin
 * @param: { Number | String } val 需要格式化的数值
 * @param: { Number } len 保留的小数位数 默认2位小数 最大不超过16位 否则会丢失精度问题（超过16位 第16位自动四舍五入了，16位之后被舍弃）
 * @param: { Number } returnType 返回类型 默认1   1:String 2:Number
 * @param: { Boolean } halfAdjust 四舍五入 默认true
 * @param: { Boolean } strict 是否是严格模式 默认true （例如：12 严格模式下 返回12.00）
 */
export const formatDigit = (val, conifg) => {
  let defaultConfig = {
    len:2, 
    returnType:1, 
    halfAdjust:true, 
    strict:true,
    ...conifg
  }
  let {len,returnType,halfAdjust,strict} = defaultConfig;
  if(!val) return ''
  if(isNaN(Number(val))) return ''
  let newVal = '';
  val = Number(val) + ''; //转换成字符串数字 判断小数点后面的长度
  let decimalArr = val.split(".");
  if (decimalArr[1]) {
    // 如果已经存在小数点
    if(halfAdjust){
      newVal = Number(val).toFixed(len);
    }else{
      if(strict){
        // 严格模式下 小数部分不足位数 自动补0
        let decimalLen = decimalArr[1].length
        if( decimalLen< len){
          for(let i=0; i<len-decimalLen; i++){
            decimalArr[1] += '0'
          }
        }
      }
      newVal =  `${decimalArr[0]}.${decimalArr[1].substring(0, len)}`;
    }
  } else {
    if(strict){
      newVal =  Number(val).toFixed(len);
    }else{
      newVal =  decimalArr[0];
    }
  }
   return returnType === 1 ? newVal : Number(newVal)
};
